package com.example.spring.security.demo.config;

import com.example.spring.security.demo.component.*;
import com.example.spring.security.demo.filter.MyJwtAuthenticationTokenFilter;
import com.example.spring.security.demo.filter.MyJwtAuthenticationTokenTestFilter;
import com.example.spring.security.demo.service.MyUserDetailTestService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * @ClassName MySecurityConfig
 * @Description
 * @Author lichuanqi
 * @Date 2022/5/14 12:03
 * @Version 1.0
 **/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityTestConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private MyJwtAuthenticationTokenTestFilter myJwtAuthenticationTokenTestFilter;

    @Resource
    private MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    @Resource
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;


    @Resource
    private MyUserDetailTestService myUserDetailTestService;

    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;


    /**
     * @Author lichuanqi
     * @Description 更改默认的用户密码加密校验器，默认的密码加密校验器需要在原密码前加入{加密方式}非常不方便
     * @Date 12:10 2022/5/14
     * @Param []
     * @return org.springframework.security.crypto.password.PasswordEncoder
     **/
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //关闭csrf
                .csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .rememberMe().userDetailsService(myUserDetailTestService)
                .and()
                .authorizeRequests()
                // 对于登录接口 允许匿名访问,只能匿名访问，如果已登录就会报错
                .antMatchers("/user/login").anonymous()
//                .antMatchers("/testCors").hasAuthority("system:dept:list222")
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated().and()
                .formLogin().loginProcessingUrl("/user/login")
                .successHandler(myAuthenticationSuccessHandler)
                .failureHandler(myAuthenticationFailureHandler)
                .and()
                .logout().logoutUrl("/user/login").logoutSuccessHandler(myLogoutSuccessHandler);
        //加入拦截器，放到UsernamePasswordAuthenticationFilter所在的位置
        http.addFilterBefore(myJwtAuthenticationTokenTestFilter, UsernamePasswordAuthenticationFilter.class);

        //配置异常处理器
        http.exceptionHandling()
                //配置认证失败处理器
                .authenticationEntryPoint(myAuthenticationEntryPoint)
                .accessDeniedHandler(myAccessDeniedHandler);

        //允许跨域
        http.cors();
    }
}
